#include "diagramscene.h"
#include <QMimeData>
#include <QDebug>
#include <QTextCursor>
#include "startstep.h"
#include "endstep.h"
#include "loopstep.h"
#include "conditionstep.h"
#include "geometrystep.h"
#include "gridstep.h"
#include "soverstep.h"
#include "backdealstep.h"
#include "single.h"
#include "relation.h"
#include "workflowxml.h"
DiagramScene::DiagramScene(QObject *parent) : QGraphicsScene(parent)
{
    setSceneRect(-1000,-1000,1000,1000);
}


void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    if (mouseEvent->button() != Qt::LeftButton)
        return;
    if(!selectedItems().isEmpty()&&selectedItems().first()->type() == Relation::Type)
    {
        QGraphicsScene::mousePressEvent(mouseEvent);
    }
    if(InsertLine == Single::install().getMode())
    {
        line = new QGraphicsLineItem(QLineF(mouseEvent->scenePos(),
                                    mouseEvent->scenePos()));

        line->setPen(QPen(Qt::black, 5));
        line->setZValue(1000);
        addItem(line);
    }
    QGraphicsScene::mousePressEvent(mouseEvent);
}

void DiagramScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    if (Single::install().getMode() == InsertLine && line != nullptr) {
        QLineF newLine(line->line().p1(), mouseEvent->scenePos());
        line->setLine(newLine);
        line->setZValue(1000);


    }
    QGraphicsScene::mouseMoveEvent(mouseEvent);

}

void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    if (line != nullptr && Single::install().getMode() == InsertLine)
    {
        QList<QGraphicsItem *> startItems = items(line->line().p1());
        if (startItems.count() && startItems.first() == line)
        {
            startItems.removeFirst();
        }
        QList<QGraphicsItem *> endItems = items(line->line().p2());
        if (endItems.count() && endItems.first() == line)
        {
            endItems.removeFirst();
        }

       removeItem(line);
       delete line;
       line = nullptr;
        if (startItems.count() > 0 && endItems.count() > 0 &&
            startItems.first()->type() == Port::Type &&
            endItems.first()->type() == Port::Type &&
            startItems.first() != endItems.first())
        {
            Port *startItem = qgraphicsitem_cast<Port *>(startItems.first());
            Port *endItem = qgraphicsitem_cast<Port *>(endItems.first());
            {
                if(startItem->parentItem() != endItem->parentItem() && !workFlow->containCport(startItem->getCport()) && !workFlow->containCport(endItem->getCport()))
                {
                    qDebug()<<endItem->type();
                    CRelationProperty* property = new CRelationProperty{QString("realtion_%1").arg(++relationCount),"WFIORelation"};
                    startItem->getCport()->setPos(startItem->scenePos());
                    endItem->getCport()->setPos(endItem->scenePos());
                    CRelation* crelation = new CRelation(property,startItem->getCport(),endItem->getCport());
                    Relation *relation = new Relation(crelation);
                    relation->setZValue(-1000.0);
                    addItem(relation);
                    relation->updatePosition();
                    workFlow->addRelation(crelation);
                    CLink* startLink = new CLink(startItem->getCport(),crelation);
                    CLink* endLink = new CLink(endItem->getCport(),crelation);
                    workFlow->addLink(startLink);
                    workFlow->addLink(endLink);

                }
            }
        }
    }
    QGraphicsScene::mouseReleaseEvent(mouseEvent);
}

void DiagramScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
    if (event->mimeData()->hasFormat(myMimeType()))
        event->accept();
    else
        event->ignore();
}

void DiagramScene::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
    event->accept();
}

void DiagramScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
        event->setDropAction(Qt::MoveAction);
        event->accept();
}

void DiagramScene::dropEvent(QGraphicsSceneDragDropEvent *event)
{

    QPixmap pix;
    QString name;
    int type;
    int index=0; //自定义控件下标

    QByteArray itemData = event->mimeData()->data(myMimeType());
    QDataStream dataStream(&itemData, QIODevice::ReadOnly);
    dataStream >> type>>index;

    StepBase * step=nullptr;
    if(index == 0)   //通用组件
    {
        step = createStep(type);

    }
    else //自定义组件
    {

    }
    if(step)
    {
        CPort* cport = step->createPort();
        if(step->getCstep()!=nullptr && cport!=nullptr)
        {
            step->getCstep()->addPort(cport);
        }
        cport = step->createPort();
        if(step->getCstep()!=nullptr&& cport!=nullptr)
        {
            step->getCstep()->addPort(cport);
        }
        cport = step->createPort();
        if(step->getCstep()!=nullptr&& cport!=nullptr)
        {
            step->getCstep()->addPort(cport);
        }
        cport = step->createPort();
        if(step->getCstep()!=nullptr&& cport!=nullptr)
        {
            step->getCstep()->addPort(cport);
        }
        step->setPos(event->scenePos());

        step->getCstep()->setPos(event->scenePos());
        addItem(step);

    }


    event->setDropAction(Qt::MoveAction);
    event->accept();
}



StepBase *DiagramScene::createStartStep(CStep* _cstep)
{
    StepBase *step = nullptr;
    if(startCount==0)
    {
        step = new StartStep();
        connect(step,&StepBase::destroyed,[=]()
        {
            startCount--;
        });
        if(_cstep == nullptr)
        {
            QString name =QString("通用开始组件");
            CStepProperty*  property = new CStepProperty{name,"xxx",++id,"WFBeginStep"};
            CStep* cstep = new CStep(property);
            step->setCstep(cstep);
            if(workFlow!=nullptr)
            {
                workFlow->addStep(cstep);
            }
        }
        else
        {
            step->setCstep(_cstep);
        }
        startCount++;
    }

    return step;
}

StepBase *DiagramScene::createEndStep(CStep* _cstep)
{
    StepBase *step = nullptr;
    if(endCount==0)
    {
        step = new EndStep();
        connect(step,&StepBase::destroyed,[=]()
        {
            endCount--;
        });
        if(_cstep == nullptr)
        {
            QString name =QString("通用结束组件");
            CStepProperty*  property = new CStepProperty{name,"xxx",++id,"WFEndStep"};
            CStep* cstep = new CStep(property);
            step->setCstep(cstep);
            if(workFlow!=nullptr)
            {
                workFlow->addStep(cstep);
            }
        }
        else
        {
            step->setCstep(_cstep);
        }

        endCount++;
    }
    return step;
}

StepBase *DiagramScene::createLoopStep(CStep* _cstep)
{
    StepBase *step = nullptr;

    step = new LoopStep();
    QString name;
    if(loopCount ==0)
    {
        name =QString("通用循环组件");
    }
    else
    {
        name =QString("通用循环组件_%1").arg(loopCount);
    }
    if(_cstep == nullptr)
    {
        CStepProperty*  property = new CStepProperty{name,"xxx",++id,"WFLoopStep"};
        CStep* cstep = new CStep(property);    step->setCstep(cstep);
        if(workFlow!=nullptr)
        {
            workFlow->addStep(cstep);
        }
    }
    else
    {
        step->setCstep(_cstep);
    }

    loopCount++;

    return step;
}

StepBase *DiagramScene::createConditionStep(CStep* _cstep)
{
    StepBase *step = nullptr;

    step = new ConditionStep();
    QString name;
    if(loopCount ==0)
    {
        name =QString("通用判断组件");
    }
    else
    {
        name =QString("通用判断组件_%1").arg(loopCount);
    }
    if(_cstep == nullptr)
    {
        CStepProperty*  property = new CStepProperty{name,"xxx",++id,"WFConditionStep"};
        CStep* cstep = new CStep(property);    step->setCstep(cstep);
        if(workFlow!=nullptr)
        {
            workFlow->addStep(cstep);
        }
    }
    else
    {
        step->setCstep(_cstep);
    }

    conditionCount++;

    return step;
}

StepBase *DiagramScene::createGeometryStep(CStep* _cstep)
{
    StepBase *step = nullptr;

        step = new GeometryStep();
        QString name;
        if(loopCount ==0)
        {
            name =QString("通用几何组件");
        }
        else
        {
            name =QString("通用几何组件_%1").arg(loopCount);
        }
        if(_cstep == nullptr)
        {
            CStepProperty*  property = new CStepProperty{name,"xxx",++id,"WFGeoStep"};
            CStep* cstep = new CStep(property);
            step->setCstep(cstep);

            if(workFlow!=nullptr)
            {
                workFlow->addStep(cstep);
            }
        }
        else
        {
            step->setCstep(_cstep);
        }

        geometryCount++;

    return step;
}

StepBase *DiagramScene::createGridStep(CStep* _cstep)
{
    StepBase *step = nullptr;

    step = new GridStep();
    QString name;
    if(loopCount ==0)
    {
        name =QString("通用网格组件");
    }
    else
    {
        name =QString("通用网格组件_%1").arg(loopCount);
    }
    if(_cstep == nullptr)
    {
        CStepProperty*  property = new CStepProperty{name,"xxx",++id,"WFMeshStep"};
        CStep* cstep = new CStep(property);
        step->setCstep(cstep);
        if(workFlow!=nullptr)
        {
            workFlow->addStep(cstep);
        }
    }
    else
    {
        step->setCstep(_cstep);
    }

        geometryCount++;

    return step;
}

StepBase *DiagramScene::createSoverStep(CStep* _cstep)
{
    StepBase *step = nullptr;

        step = new SoverStep();
        QString name;
        if(loopCount ==0)
        {
            name =QString("通用求解器组件");
        }
        else
        {
            name =QString("通用求解器组件_%1").arg(loopCount);
        }
        if(_cstep == nullptr)
        {
            CStepProperty*  property = new CStepProperty{name,"xxx",++id,"WFSolverStep"};
            CStep* cstep = new CStep(property);
            step->setCstep(cstep);
            if(workFlow!=nullptr)
            {
                workFlow->addStep(cstep);
            }
        }
        else
        {
            step->setCstep(_cstep);
        }

        geometryCount++;

    return step;
}

StepBase *DiagramScene::createBackDealStep(CStep* _cstep)
{
    StepBase *step = nullptr;

        step = new BackDealStep();
        QString name;
        if(loopCount ==0)
        {
            name =QString("通用后处理组件");
        }
        else
        {
            name =QString("通用后处理组件_%1").arg(loopCount);
        }
        if(_cstep == nullptr)
        {
            CStepProperty*  property = new CStepProperty{name,"xxx",++id,"WFPostStep"};
            CStep* cstep = new CStep(property);
            step->setCstep(cstep);
            if(workFlow!=nullptr)
            {
                workFlow->addStep(cstep);
            }
        }
        else
        {
            step->setCstep(_cstep);
        }

        geometryCount++;

    return step;
}


StepBase *DiagramScene::createStep(int _type)
{
    StepBase *step = nullptr;

    switch(_type)
    {
    case Start:
        step = createStartStep();
        break;
    case End:
        step = createEndStep();
        break;
    case Loop:
        step = createLoopStep();
        break;
    case Condition:
        step = createConditionStep();
        break;
    case Geometry:
        step = createGeometryStep();
        break;
    case Grid:
        step = createGridStep();
        break;
    case Sover:
        step = createSoverStep();
        break;
    case BackDeal:
        step = createBackDealStep();
        break;
    }

    return step;
}

WorkFlow *DiagramScene::getWorkFlow() const
{
    return workFlow;
}

void DiagramScene::setWorkFlow(WorkFlow *value)
{
    workFlow = value;

}

void DiagramScene::openWorkFlow(WorkFlow *_workFlow)
{
    if(_workFlow ==nullptr)
    {
        return ;
    }

    for(auto cstep : _workFlow->m_listStep)
    {
        StepBase* step =nullptr;
        CStepProperty* property = cstep->getProperty();
        if(property->type == "WFBeginStep")
        {
            step = createStartStep(cstep);
        }
        else if(property->type == "WFEndStep")
        {
            step = createEndStep(cstep);
        }
        else if(property->type == "WFLoopStep")
        {
            step = createLoopStep(cstep);
        }
        else if(property->type == "WFConditionStep")
        {
            step = createConditionStep(cstep);
        }
        else if(property->type == "WFGeoStep")
        {
            step = createGeometryStep(cstep);
        }
        else if(property->type == "WFMeshStep")
        {
            step = createGridStep(cstep);
        }
        else if(property->type == "WFSolverStep")
        {
            step = createSoverStep(cstep);
        }
        else if(property->type == "WFEndStep")
        {
            step = createBackDealStep(cstep);
        }

        for(auto cport:cstep->m_listPort)
        {
            step->createPort(cport);
        }
        QPointF p = cstep->getPos();
        step->setPos(p);
        qDebug()<<p;
        addItem(step);

        if(property->id > id)
        {
            id = property->id;
        }
    }

    for(auto crelation : _workFlow->m_listRelations)
    {
        if(crelation->dstPort()!=nullptr && crelation->srcPort()!=nullptr)
        {

            Relation *relation = new Relation(crelation);
            relation->setZValue(-1000.0);
            addItem(relation);
            emit crelation->dstPort()->updatePos();
            emit crelation->srcPort()->updatePos();
        }
    }



}
